/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.braincasedesigns.roller.factory;

import com.braincasedesigns.roller.factory.DieFactory;
import com.braincasedesigns.roller.model.FudgeDie;
import com.braincasedesigns.roller.model.GenericDicePool;
import com.braincasedesigns.roller.model.GenericDieRoll;
import com.braincasedesigns.roller.model.PercentileDie;
import com.braincasedesigns.roller.model.PolyhedralDie;
import com.braincasedesigns.roller.model.StandardModifier;
import com.braincasedesigns.roller.parser.generated.RollerLexer;
import com.braincasedesigns.roller.parser.generated.RollerParser;
import com.braincasedesigns.roller.parser.model.Modifier;
import com.braincasedesigns.roller.parser.model.RollDescription;
import com.braincasedesigns.roller.model.DicePool;
import com.braincasedesigns.roller.model.Die;
import com.braincasedesigns.roller.model.DieRoll;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;

/**
 *
 * @author jcampbel
 */
public class DieFactoryImpl implements DieFactory {

    public DieFactoryImpl() {

    }

//    public void configure(Binder binder) {
//        binder.bind(Service.class).to(ServiceImpl.class).in(Scopes.SINGLETON);
//    }

    private RollerParser getParser(String s) {

        RollerLexer lexer = new RollerLexer(new ANTLRStringStream(s));
        lexer.setText(s);

        CommonTokenStream tokens = new CommonTokenStream();
        tokens.setTokenSource(lexer);

        return new RollerParser(tokens);
    }


    public List<DicePool> getRoll(String s) {
        List<DicePool> rolls = null;
        try {
            RollerParser parser = getParser(s);
            List<RollDescription> descriptions = parser.rolls();
            rolls = new ArrayList<DicePool>();
            for (RollDescription d : descriptions) {
                DicePool pool = null;
                try {
                    pool = getDicePool(d);
                } catch (Throwable e) {
                //Ignore for now.
                }
                if (pool != null) {
                    rolls.add(pool);
                }
            }

        } catch (RecognitionException ex) {
            Logger.getLogger(DieFactoryImpl.class.getName()).log(Level.SEVERE, null, ex);
        }
        return rolls;
    }

    private DicePool getDicePool(RollDescription d) {

        //First the repeat
        int repeat = d.getRepeat();
        ///THen the  modifier
        StandardModifier modifier = null;
        Modifier m = d.getModifier();
        if (m != null) {
            modifier = new StandardModifier(m.getOperator(), m.getOperand());
        }

        DieRoll dieRoll = null;
        Die die = null;
        String faces = d.getFaces();

        if ("%".equals(faces)) {
            //DO %
            die = new PercentileDie();
        } else if ("f".equalsIgnoreCase(faces)) {
            die = new FudgeDie();
        } else if (faces.matches("^\\d+$")) {


            int sides = -1;
            try {
                sides = Integer.parseInt(faces);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("Invalid faces:" + faces, e);
            }
            //Now we assembe the actual roll
            //First the die
            die = new PolyhedralDie(sides);
        }
        dieRoll = new GenericDieRoll(d.getNumberOfDice(), die, modifier);
        return new GenericDicePool(repeat, dieRoll);
    }
}
